<script lang="ts" setup name="ComputedWatch">
import { ref, reactive, computed, watch, watchEffect, watchSyncEffect, watchPostEffect } from 'vue'

const a = ref(false);
const b = ref(0);
const c = ref(0);
const d = ref({
  a: [1, 2, 3]
});
const title = computed<string>(() => {
  return a.value ? 'a' : 'aa'
})
const changeA = () => {
  a.value = !a.value;
}
const changeB = () => {
  b.value ++;
}
const changeC = () => {
  c.value ++;
}
const changeD = () => {
  d.value.a.push(6);
}

// 单个 ref
watch(
  a, 
  (newVal, oldVal) => {
    console.log('单个 ref', newVal, oldVal)
  },
  // { once: true }
)

// getter 函数
// watch(
//   () => b.value + c.value,
//   (sum) => {
//     console.log('getter 函数', sum)
//   }
// )

// // 多个来源组成的数组
// watch([b, () => c.value], ([newB, newC]) => {
//   console.log('多个来源组成的数组', newB, newC)
// })

// 深度监听
watch(d, (newVal, oldVal) => {
  console.log('深度侦听', newVal, oldVal)
}, {
  immediate: true,
  deep: true
})

// 不能直接侦听响应式对象的属性值
const obj = reactive({ count: 0 })
// 错误，因为 watch() 得到的参数是一个 number
// watch(obj.count, (count) => {
//   console.log('侦听对象的属性值', count)
// })
// 提供一个 getter 函数
watch(
  () => obj.count,
  (count) => {
    console.log(`() => obj.count: ${count}`)
  }
)
const changeCount = () => {
  obj.count ++;
}

// watchEffect 不用明确指出监听的数据（函数中用到哪些属性，那就监听哪些属性）在初始化时会执行一次回调函数。
// 如果在if条件里使用了或运算符||，它会按照条件顺序进行监听，一旦前面的条件符合，则后续的条件将不会监听。
watchEffect(() => {
  const x = a.value;
  const y = b.value + c.value;
  console.log('watchEffect', x, y);
})
const changeBC = () => {
  changeB();
  changeC();
}
// watchSyncEffect 使用flush: 'sync'选项时的别名
// 它是一个同步的监视器，每当依赖变化时立即触发回调函数，而不会等待下一次事件循环。
// watchSyncEffect(() => {
//   console.log('watchSyncEffect', b.value);
//   console.log('watchSyncEffect', c.value);
// })

// 回调函数会在 DOM 更新之后被调用，确保回调函数执行时可以获取到更新后的 DOM。
// watchPostEffect 使用flush: 'post'选项时的别名
// watchPostEffect(() => {
//   console.log('watchSyncEffect', b.value);
//   console.log('watchSyncEffect', c.value);
// })
</script>

<template>
  <div>
    <div>{{ 'title:' + title }}</div>
    <button @click="changeA">改变a</button>
    <div>{{ 'b:' + b }}</div>
    <button @click="changeB">改变b</button>
    <div>{{ 'c:' + c }}</div>
    <button @click="changeC">改变c</button>
    <div>{{ 'd:' + d.a }}</div>
    <button @click="changeD">改变d</button>
    <div>{{ 'obj.count:' + obj.count }}</div>
    <button @click="changeCount">改变count</button>
    <button @click="changeBC">改变changeBC</button>
  </div>
</template>
